package com.qire.other.advert;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;

import com.qire.other.advert.listener.AdvertClosedListener;
import com.qire.other.advert.listener.AdvertCompleteListener;
import com.qire.other.advert.listener.AdvertErrorListener;
import com.qire.other.advert.listener.AdvertListener;
import com.qire.other.advert.listener.AdvertLoadedListener;
import com.qire.other.advert.listener.AdvertShowedListener;
import com.qire.other.advert.listener.AdvertSkippedListener;
import com.qire.other.advert.listener.AdvertStartListener;
import com.qire.other.advert.listener.AdvertTimeoutListener;

import androidx.fragment.app.FragmentActivity;

/**
 * 第三方广告门面类
 */
public abstract class Advert {

    /** 广告代码 */
    protected final String advertCode;

    protected int advertWidth, advertHeight;
    private AdvertLoadedListener loadedListener;
    private AdvertStartListener startListener;
    private AdvertShowedListener showedListener;
    private AdvertClosedListener closedListener;
    private AdvertSkippedListener skippedListener;
    private AdvertCompleteListener completeListener;
    private AdvertErrorListener errorListener;
    private AdvertTimeoutListener timeoutListener;

    public Advert(String advertCode) {
        this.advertCode = advertCode;
    }

    /**
     * 广告申请使用规格，广告会按照这个大小规格来申请，一般来说广告大小应该趋近这个大小，但是有些广告平台的大小并不是我们控制，
     * 而是由我们提交一个期望大小来尽可能匹配这个比例尺寸的广告，所以这个如果不设置可能会影响到具体布局。
     * @param advertWidth   期望广告宽度
     * @param advertHeight  期望广告高度,如果为0则会自适应高度
     * @return 广告实体
     */
    public Advert setSize(int advertWidth, int advertHeight) {
        this.advertWidth    = advertWidth;
        this.advertHeight   = advertHeight;

        return this;
    }

    public Advert setAdvertListener(AdvertListener listener) {
        setLoadedListener(listener);
        setStartListener(listener);
        setShowedListener(listener);
        setClosedListener(listener);
        setCompleteListener(listener);
        setErrorListener(listener);
        setTimeoutListener(listener);
        return this;
    }

    public Advert setLoadedListener(AdvertLoadedListener loadedListener) {
        this.loadedListener = loadedListener;
        return this;
    }

    public Advert setStartListener(AdvertStartListener startListener) {
        this.startListener = startListener;
        return this;
    }

    public Advert setShowedListener(AdvertShowedListener showedListener) {
        this.showedListener = showedListener;
        return this;
    }

    public Advert setClosedListener(AdvertClosedListener closedListener) {
        this.closedListener = closedListener;
        return this;
    }

    public Advert setSkippedListener(AdvertSkippedListener skippedListener) {
        this.skippedListener = skippedListener;
        return this;
    }

    public Advert setCompleteListener(AdvertCompleteListener completeListener) {
        this.completeListener = completeListener;
        return this;
    }

    public Advert setErrorListener(AdvertErrorListener errorListener) {
        this.errorListener = errorListener;
        return this;
    }

    public Advert setTimeoutListener(AdvertTimeoutListener timeoutListener) {
        this.timeoutListener = timeoutListener;
        return this;
    }

    protected void onLoaded() {
        if(loadedListener != null) {
            loadedListener.onLoaded();
        }
    }

    protected void onStart() {
        if(startListener != null) {
            startListener.onStart();
        }
    }

    protected void onShowed() {
        if(showedListener != null) {
            showedListener.onShowed();
        }
    }

    protected void onClosed() {
        if(closedListener != null) {
            closedListener.onClosed();
        }
    }

    protected void onSkipped() {
        if(skippedListener != null) {
            skippedListener.onSkipped();
        }
    }

    protected void onPlayComplete() {
        if(completeListener != null) {
            completeListener.onPlayComplete();
        }
    }

    protected void onError() {
        if(errorListener != null) {
            errorListener.onError();
        }
    }

    protected void onTimeout() {
        if(timeoutListener != null) {
            timeoutListener.onTimeout();
        }
    }


    /**
     * 播放激励视频广告
     * @param activity 发起广告的页面
     */
    public abstract void playVideo(FragmentActivity activity);

    /**
     * 注入横幅广告
     * @param viewParent 用来装载广告的父容器控件，广告加载后将会被插入到改容器中，可以通过调整容器所在位置来决定广告显示大致位置。
     * @param layoutRid  自定义渲染布局资源ID
     */
    public void injectionBanner(ViewGroup viewParent, int layoutRid) {
        injectionBanner(new NowAdvertDockingDevice(viewParent), layoutRid);
    }
    /**
     * 注入横幅广告
     * @param advertDockingDevice 用来完成广告与插入视图容器的关联，
     * @param layoutRid  自定义渲染布局资源ID
     */
    public abstract void injectionBanner(AdvertDockingDevice advertDockingDevice, int layoutRid);

    /**
     * 注入信息流广告
     * @param viewParent 用来装载广告的父容器控件，广告加载后将会被插入到改容器中，可以通过调整容器所在位置来决定广告显示大致位置。
     */
    public void injectionInfoFlow(ViewGroup viewParent) {
        injectionInfoFlow(new NowAdvertDockingDevice(viewParent));
    }
    /**
     * 注入信息流广告
     * @param advertDockingDevice 用来完成广告与插入视图容器的关联，
     */
    public abstract void injectionInfoFlow(AdvertDockingDevice advertDockingDevice);

    /**
     * 注入开屏广告（启动广告）
     * @param viewParent 用来装载广告的父容器控件，广告加载后将会被插入到改容器中，可以通过调整容器所在位置来决定广告显示大致位置。
     */
    public void injectionSplash(ViewGroup viewParent) {
        injectionSplash(viewParent, true, 3500);
    }
    public void injectionSplash(ViewGroup viewParent, boolean disableCountdown, int timeOut) {
        injectionSplash(new NowAdvertDockingDevice(viewParent), disableCountdown, timeOut);
    }
    /**
     * 注入开屏广告（启动广告）
     * @param advertDockingDevice   用来完成广告与插入视图容器的关联，
     * @param disableCountdown      是否禁用用倒计时 true 禁用，false 启用
     * @param timeOut               超时时间 建议 > 3500ms
     */
    public abstract void injectionSplash(AdvertDockingDevice advertDockingDevice, boolean disableCountdown, int timeOut);

    /**
     * 提供一个默认现在绑定的广告视图绑定器，接受到广告视图时会立马与需要插入的控件完成绑定。
     * 如果完成绑定后，会释放持有的父视图容器
     */
    private class NowAdvertDockingDevice implements AdvertDockingDevice {
        ViewGroup viewParent;
        private NowAdvertDockingDevice(ViewGroup viewParent) {
            this.viewParent = viewParent;
        }

        @Override
        public Context getContext() {
            return viewParent.getContext();
        }

        @Override
        public void insert(View advertView) {
            if(advertView != null) {
                viewParent.addView(advertView);
                viewParent = null;
            }
        }

        @Override
        public void remove(View advertView) {
            viewParent.removeView(advertView);
        }

        @Override
        public void removeAll() {
            viewParent.removeAllViews();
        }

        @Override
        public void destroy() {
            viewParent.removeAllViews();
            viewParent = null;
        }
    }

}
